#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
飞书Token管理器 - 自动读取和刷新user_access_token
"""

import os
import time
from typing import Optional
import requests
from dotenv import load_dotenv  
load_dotenv()

class TokenManager:
    """飞书Token管理器 - 基于.env文件的统一配置"""
    
    def __init__(self, env_file: str = ".env"):
        self.env_file = env_file
        self.refresh_url = "https://open.feishu.cn/open-apis/authen/v2/oauth/token"
        # 重新加载环境变量以确保最新状态
        load_dotenv(self.env_file, override=True)
    
    def _validate_env_vars(self) -> bool:
        """验证环境变量是否完整"""
        if not self._has_required_env_vars():
            print("[警告] 缺少必要的环境变量，请检查.env文件")
            return False
        return True
    
    def _has_required_env_vars(self) -> bool:
        """检查是否有必要的环境变量"""
        required_vars = [
            "FEISHU_APP_ID",
            "FEISHU_APP_SECRET", 
            "FEISHU_USER_ACCESS_TOKEN",
            "FEISHU_REFRESH_TOKEN"
        ]
        # expires_in和expires_at至少要有一个
        has_expires = os.getenv("FEISHU_USER_ACCESS_TOKEN_EXPIRES_IN") or os.getenv("FEISHU_USER_ACCESS_TOKEN_EXPIRES_AT")
        return all(os.getenv(var) for var in required_vars) and has_expires
    
    def _get_env_token_data(self) -> dict:
        """从环境变量获取token数据"""
        try:
            expires_in = int(os.getenv("FEISHU_USER_ACCESS_TOKEN_EXPIRES_IN", "7200"))
            expires_at = int(os.getenv("FEISHU_USER_ACCESS_TOKEN_EXPIRES_AT", "0"))
            
            # 如果没有expires_at，则使用当前时间+expires_in计算
            if expires_at == 0:
                expires_at = time.time() + expires_in
            
            return {
                "app_id": os.getenv("FEISHU_APP_ID"),
                "app_secret": os.getenv("FEISHU_APP_SECRET"),
                "access_token": os.getenv("FEISHU_USER_ACCESS_TOKEN"),
                "refresh_token": os.getenv("FEISHU_REFRESH_TOKEN"),
                "expires_at": expires_at,
                "expires_in": expires_in
            }
        except (ValueError, TypeError) as e:
            print(f"[错误] 环境变量格式错误: {e}")
            return {}
        except Exception as e:
            print(f"[错误] 读取环境变量失败: {e}")
            return {}
    
    def get_valid_token(self) -> Optional[str]:
        """获取有效的user_access_token"""
        # 重新加载环境变量确保最新状态
        load_dotenv(self.env_file, override=True)
        
        if not self._validate_env_vars():
            return None
            
        data = self._get_env_token_data()
        if not data or not data.get("access_token"):
            print("[错误] 环境变量中缺少有效的access_token")
            return None
        
        # 智能提前刷新：总有效期的1/4或最少3600秒
        current_time = time.time()
        expires_at = data.get("expires_at", 0)

        total_lifetime = expires_at - data.get("init_time", expires_at - 7200)
        refresh_buffer = max(total_lifetime * 0.25, 3600)  # 25%或3600秒
        
        if current_time >= (expires_at - refresh_buffer):
            print(f"[信息] Token将在{(expires_at - current_time)/60:.1f}分钟后过期，正在刷新...")
            if not self._refresh_token(data):
                return None
            # 刷新后重新获取token
            load_dotenv(self.env_file, override=True)
            data = self._get_env_token_data()
        
        return data.get("access_token")
    
    def _update_env_file(self, updates: dict) -> bool:
        """更新.env文件中的指定变量"""
        try:
            # 读取现有的.env文件内容
            env_lines = []
            if os.path.exists(self.env_file):
                with open(self.env_file, 'r', encoding='utf-8') as f:
                    env_lines = f.readlines()
            
            # 更新或添加变量
            updated_vars = set()
            for i, line in enumerate(env_lines):
                line = line.strip()
                if '=' in line and not line.startswith('#'):
                    var_name = line.split('=')[0].strip()
                    if var_name in updates:
                        env_lines[i] = f"{var_name}={updates[var_name]}\n"
                        updated_vars.add(var_name)
            
            # 添加新变量
            for var_name, value in updates.items():
                if var_name not in updated_vars:
                    env_lines.append(f"{var_name}={value}\n")
            
            # 写回文件
            with open(self.env_file, 'w', encoding='utf-8') as f:
                f.writelines(env_lines)
            
            return True
        except Exception as e:
            print(f"[错误] 更新.env文件失败: {e}")
            return False
    
    def _refresh_token(self, data: dict) -> bool:
        """刷新access_token"""
        refresh_token = data.get("refresh_token")
        if not refresh_token:
            print("[错误] 没有refresh_token，请重新初始化")
            return False
            
        # 检查必要的app信息
        if not data.get("app_id") or not data.get("app_secret"):
            print("[错误] 缺少app_id或app_secret，请重新初始化")
            return False
            
        try:
            payload = {
                "grant_type": "refresh_token",
                "client_id": data["app_id"],
                "client_secret": data["app_secret"],
                "refresh_token": refresh_token
            }
            
            print(f"[信息] 正在向 {self.refresh_url} 发送刷新请求...")
            response = requests.post(
                self.refresh_url, 
                json=payload,
                headers={"Content-Type": "application/json; charset=utf-8"},
                timeout=30
            )
            
            if response.status_code != 200:
                print(f"[错误] HTTP请求失败，状态码: {response.status_code}")
                return False
            
            result = response.json()
            print(f"[调试] 刷新响应: {result}")
            
            if result.get("code") == 0:
                # 更新.env文件中的token信息
                current_time = time.time()
                expires_at = int(current_time + result["expires_in"])
                
                updates = {
                    "FEISHU_USER_ACCESS_TOKEN": result["access_token"],
                    "FEISHU_USER_ACCESS_TOKEN_EXPIRES_IN": str(result["expires_in"]),
                    "FEISHU_USER_ACCESS_TOKEN_EXPIRES_AT": str(expires_at)
                }
                
                # 如果返回了新的refresh_token，也要更新
                if "refresh_token" in result:
                    updates["FEISHU_REFRESH_TOKEN"] = result["refresh_token"]
                
                if self._update_env_file(updates):
                    print(f"[成功] Token刷新完成，新token有效期: {result['expires_in']}秒")
                    return True
                else:
                    print("[错误] Token刷新成功但更新.env文件失败")
                    return False
            else:
                error_code = result.get("code", "未知")
                error_desc = result.get("error_description", result.get("error", "未知错误"))
                print(f"[错误] Token刷新失败 (错误码:{error_code}): {error_desc}")
                
                # 处理特定错误码
                if error_code in [20037, 20064, 20073]:  # refresh_token过期或已使用
                    print("[提示] refresh_token已过期或已使用，需要重新获取授权")
                elif error_code == 20074:  # 应用未开启刷新功能
                    print("[提示] 应用未开启token刷新功能，请检查应用配置")
                
                return False
                
        except requests.exceptions.Timeout:
            print("[错误] 请求超时，请检查网络连接")
            return False
        except requests.exceptions.ConnectionError:
            print("[错误] 网络连接错误，请检查网络设置")
            return False
        except Exception as e:
            print(f"[错误] Token刷新异常: {e}")
            return False
    
    def setup_tokens(self) -> None:
        """交互式初始化token到.env文件"""
        print("=== 飞书Token初始化 ===\n")
        
        # 检查是否已有完整配置
        if self._has_required_env_vars():
            print("检测到完整的环境变量配置，当前配置有效。")
            return
        
        # 尝试从环境变量读取默认值
        app_id = os.getenv("FEISHU_APP_ID", "")
        app_secret = os.getenv("FEISHU_APP_SECRET", "")
        access_token = os.getenv("FEISHU_USER_ACCESS_TOKEN", "")
        refresh_token = os.getenv("FEISHU_REFRESH_TOKEN", "")
        expires_in = os.getenv("FEISHU_USER_ACCESS_TOKEN_EXPIRES_IN", "7200")
        
        # 交互式输入，显示默认值
        app_id = input(f"请输入APP_ID [{app_id}]: ").strip() or app_id
        app_secret = input(f"请输入APP_SECRET [{app_secret[:8]}...]: ").strip() or app_secret
        access_token = input(f"请输入access_token [{access_token[:20] if access_token else ''}...]: ").strip() or access_token
        refresh_token = input(f"请输入refresh_token [{refresh_token[:20] if refresh_token else ''}...]: ").strip() or refresh_token
        expires_in = input(f"请输入expires_in（秒，默认{expires_in}）: ").strip() or expires_in
        
        if not all([app_id, app_secret, access_token, refresh_token]):
            print("[错误] 所有字段都必须填写")
            return
            
        try:
            expires_in = int(expires_in)
            current_time = time.time()
            expires_at = int(current_time + expires_in)
            
            updates = {
                "FEISHU_APP_ID": app_id,
                "FEISHU_APP_SECRET": app_secret,
                "FEISHU_USER_ACCESS_TOKEN": access_token,
                "FEISHU_REFRESH_TOKEN": refresh_token,
                "FEISHU_USER_ACCESS_TOKEN_EXPIRES_IN": str(expires_in),
                "FEISHU_USER_ACCESS_TOKEN_EXPIRES_AT": str(expires_at)
            }
            
            if self._update_env_file(updates):
                print(f"[成功] Token已保存到 {self.env_file}")
            else:
                print("[错误] 保存到.env文件失败")
            
        except ValueError:
            print("[错误] expires_in必须是数字")
        except Exception as e:
            print(f"[错误] 保存失败: {e}")
    
    def test_refresh(self) -> None:
        """测试token刷新功能"""
        print("=== 测试Token刷新 ===")
        
        # 重新加载环境变量
        load_dotenv(self.env_file, override=True)
        
        if not self._validate_env_vars():
            print("[错误] 环境变量不完整，请先运行setup初始化")
            return
            
        data = self._get_env_token_data()
        if not data or not data.get("refresh_token"):
            print("[错误] 没有refresh_token，无法测试刷新")
            return
            
        print(f"[信息] 当前token过期时间: {time.ctime(data.get('expires_at', 0))}")
        result = self._refresh_token(data)
        if result:
            print("[成功] 刷新测试通过")
        else:
            print("[失败] 刷新测试失败")


if __name__ == "__main__":
    import sys
    manager = TokenManager()
    
    if len(sys.argv) > 1:
        if sys.argv[1] == "setup":
            manager.setup_tokens()
        elif sys.argv[1] == "test":
            manager.test_refresh()
        elif sys.argv[1] == "check":
            token = manager.get_valid_token()
            if token:
                print(f"[成功] 当前token: {token[:20]}...")
            else:
                print("[失败] 无有效token")
    else:
        # 默认测试get_valid_token方法
        print("=== 测试TokenManager ===")
        print("用法:")
        print("  python src/token_manager.py setup  # 初始化token到.env文件")
        print("  python src/token_manager.py test   # 测试刷新功能")
        print("  python src/token_manager.py check  # 检查token状态")
        print()
        
        token = manager.get_valid_token()
        if token:
            print(f"[成功] 获取到token: {token[:20]}...")
        else:
            print("[提示] 没有有效token，请检查.env文件或运行setup初始化")